package com.example.gokchinesefoodmapmcdev.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.gokchinesefoodmapmcdev.dao.*;
import com.example.gokchinesefoodmapmcdev.entity.MerchantInfo;
import com.example.gokchinesefoodmapmcdev.entity.deliver.LocationDeliver;
import com.example.gokchinesefoodmapmcdev.entity.dto.OrderSubmitDTO;
import com.example.gokchinesefoodmapmcdev.entity.goods.GoodAttrVal;
import com.example.gokchinesefoodmapmcdev.entity.goods.GoodsInfo;
import com.example.gokchinesefoodmapmcdev.entity.goods.GoodsSku;
import com.example.gokchinesefoodmapmcdev.entity.membercart.MemberCart;
import com.example.gokchinesefoodmapmcdev.entity.membercart.MemberCartItem;
import com.example.gokchinesefoodmapmcdev.entity.order.OrderInfo;
import com.example.gokchinesefoodmapmcdev.entity.order.OrderNote;
import com.example.gokchinesefoodmapmcdev.entity.order.OrderSku;
import com.example.gokchinesefoodmapmcdev.entity.sys.SysUser;
import com.example.gokchinesefoodmapmcdev.service.MemberCartService;
import com.example.gokchinesefoodmapmcdev.util.MyTranslateTools;
import com.example.gokchinesefoodmapmcdev.util.ResultData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MemberCartServiceImpl implements MemberCartService {

    private static final Logger logger = LoggerFactory.getLogger(MemberCartServiceImpl.class);

    @Autowired
    private MemberCartDAO memberCartDAO;

    @Autowired
    private MemberCartItemDAO memberCartItemDAO;

    @Autowired
    private SysUserDAO sysUserDAO;

    @Autowired
    private GoodAttrValDAO goodAttrValDAO;

    @Autowired
    private GoodsSkuDAO goodsSkuDAO;

    @Autowired
    private MerchantInfoDAO merchantInfoDAO;

    @Autowired
    private OrderNoteDAO orderNoteDAO;

    @Autowired
    private OrderInfoDAO orderInfoDAO;

    @Autowired
    private OrderSkuDAO orderSkuDAO;

    @Autowired
    private LocationDeliverDAO locationDeliverDAO;


    /**
     * 实现添加商品到购物车中的业务逻辑处理
     *      需要向两张表中插入数据member_cart、member_cart_item
     *      分析：如果当前用户有购物车信息，就不向member_cart中添加数据了，直接取用购物车id
     *
     * @param goodsInfo     前端传入的部分商品信息（商品id、名字、描述、商户id）
     * @param number        购物买数量
     * @param attrSymbolPath    商品规格码组合，按照规格排序用逗号隔开
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer addMemberCart(GoodsInfo goodsInfo, Integer number, String attrSymbolPath) {
        /*
                1.1 如果当前用户还没有添加过购物车：向数据库中添加用户和购物车id的映射信息
                1.2 如果当前用户已有购物车信息，只添加购物车中的物品信息member_cart_item即可
         */
        // 创建和修改时间
        Date gmtCreated = new Date();
        // 获取当前用户信息
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser sysUser = sysUserDAO.selectOne(new QueryWrapper<SysUser>().eq("username", userDetails.getUsername()));

        // 查询是否有购物车信息
        MemberCart memberCart = memberCartDAO.selectOne(new QueryWrapper<MemberCart>().eq("user_id", sysUser.getUserId()));
        if(memberCart == null) {
            MemberCart memberCart1 = new MemberCart(null, sysUser.getUserId().intValue(), gmtCreated, gmtCreated);
            int result = memberCartDAO.insert(memberCart1);
        }

        // 2. 向数据库中添加购物详细信息
        Integer[] goodAttrValId = getArrayAttrSymbolPath(attrSymbolPath);
        List<GoodAttrVal> goodAttrVals = goodAttrValDAO.selectList(new QueryWrapper<GoodAttrVal>().in("id", goodAttrValId));

        // 查询商品库中信息
        StringBuilder attrSymbolText = new StringBuilder();
        if(goodAttrValId != null && !goodAttrVals.isEmpty()){
            for (GoodAttrVal goodAttrVal : goodAttrVals) {
                attrSymbolText.append("“" + goodAttrVal.getAttrValue() + "”");
            }
        }

        GoodsSku goodsSku = goodsSkuDAO.selectOne(new QueryWrapper<GoodsSku>()
                                                        .eq("attr_symbol_text", attrSymbolText.toString())
                                                        .eq("good_id", goodsInfo.getId()));

        MemberCartItem memberCartItem = getMemberCartItem(memberCart, goodsInfo, goodsSku, number, gmtCreated);
        int result2 = memberCartItemDAO.insert(memberCartItem);

        return result2;
    }

    /**
     * 实现删除购物车物品逻辑
     * @param ids   购物车项id数组
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer removeMemberCartItem(Integer[] ids) {
        // 为防止出错，添加查询当前用户，当前用户只能删除自己的购物车物品信息
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser sysUser = sysUserDAO.selectOne(new QueryWrapper<SysUser>().eq("username", userDetails.getUsername()));
        MemberCart memberCart = memberCartDAO.selectOne(new QueryWrapper<MemberCart>().eq("user_id", sysUser.getUserId()));
        if(memberCart == null){
            return 0;
        }
        List<MemberCartItem> memberCartItems = memberCartItemDAO.selectList(new QueryWrapper<MemberCartItem>().eq("cart_id", memberCart.getId()));
        for (Integer id : ids) {
            if(!memberCartItems.contains(id)){
                try {
                    throw new Exception("非法访问请求删除购物车信息");
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
            }
        }

        // 返回影响行数
        int result = memberCartItemDAO.delete(new QueryWrapper<MemberCartItem>().in("id", ids));
        return result;
    }

    /**
     * 修改购物车项的规格和数量业务逻辑处理
     * @param memberCartItem  简单封装后的购物车信息（购物车项id，商品Id，商品规格文字，修改时间）
     * @param attrSymbolPath
     * @param number
     * @return
     */
    @Override
    public Integer updateMemberCartItem(MemberCartItem memberCartItem, String attrSymbolPath, Integer number) {
        // 查询到该购物车项信息
        MemberCartItem memberCartItem1 = memberCartItemDAO.selectOne(new QueryWrapper<MemberCartItem>().eq("id", memberCartItem.getId()));

        // 1. 查询规格信息，重新设置商品规格
        Integer[] goodAttrValId = getArrayAttrSymbolPath(attrSymbolPath);
        List<GoodAttrVal> goodAttrVals = goodAttrValDAO.selectList(new QueryWrapper<GoodAttrVal>().in("id", goodAttrValId));
        StringBuilder attrSymbolText = new StringBuilder();
        if(goodAttrValId != null && !goodAttrVals.isEmpty()){
            for (GoodAttrVal goodAttrVal : goodAttrVals) {
                attrSymbolText.append("“" + goodAttrVal.getAttrValue() + "”");
            }
        }
        memberCartItem1.setProductDesc(attrSymbolText.toString());
        memberCartItem1.setGmtUpdated(memberCartItem.getGmtUpdated());

        // 2. 根据规格再查价格、库存
        GoodsSku goodsSku = goodsSkuDAO.selectOne(new QueryWrapper<GoodsSku>()
                                                    .eq("attr_symbol_text", attrSymbolText.toString())
                                                    .eq("good_id", memberCartItem.getGoodId()));

        // 3.1 如果库存不足，则修改失败
        if(goodsSku == null || goodsSku.getStock() < number){
            return -1;
        }

        // 3.2 重新计算价格
        BigDecimal price = goodsSku.getPrice().multiply(new BigDecimal(number));
        memberCartItem1.setPrice(price);
        memberCartItem1.setNumber(number);

        // 修改数据库内容
        int result = memberCartItemDAO.updateById(memberCartItem1);

        return result;
    }

    /**
     * 根据用户名（数据库中唯一）查询该用户的购物车信息
     * @param username
     * @return
     */
    @Override
    public List<Map<String, Object>> findMemberCartItemByUser(String username) {
        // 查询用户信息
        SysUser sysUser = sysUserDAO.selectOne(new QueryWrapper<SysUser>().eq("username", username));
        // 查询购物信息
        MemberCart memberCart = memberCartDAO.selectOne(new QueryWrapper<MemberCart>().eq("user_id", sysUser.getUserId()));
        if(memberCart == null){
            return new ArrayList<>();
        }
        // 查询购物车项信息
        List<MemberCartItem> memberCartItems = memberCartItemDAO.selectList(new QueryWrapper<MemberCartItem>().eq("cart_id", memberCart.getId()));
        if(memberCartItems.isEmpty()){
            return new ArrayList<>();
        }

        List<Map<String, Object>> result = new ArrayList<>();
        // 遍历填充其他需要的数据
        for (MemberCartItem memberCartItem : memberCartItems) {
            Map<String, Object> map = MyTranslateTools.transEntityToMap(memberCartItem);
            // 商户名字
            MerchantInfo merchantInfo = merchantInfoDAO.selectOne(new QueryWrapper<MerchantInfo>().eq("id", memberCartItem.getMerchantId()));
            map.put("merchantName", merchantInfo.getMerchantName());

            // 规格号
            GoodsSku goodsSku = goodsSkuDAO.selectOne(new QueryWrapper<GoodsSku>().eq("id", memberCartItem.getSkuId()));
            map.put("attrSymbolPath", goodsSku.getAttrSymbolPath());
            result.add(map);
        }

        return result;
    }

    /**
     * 从购物车确认订单信息（此时未支付，也未生成订单信息，只返回勾选中的商品信息即可）
     * @param ids 购物车项id数组
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public ResultData confirmOrderFromCart(Integer[] ids, String username) {
        // 1. 根据购物车项id查询确认的订单信息
        List<MemberCartItem> memberCartItems = memberCartItemDAO.selectList(new QueryWrapper<MemberCartItem>().in("id", ids));
        // 添加内容
        List<Map<String, Object>> items = new ArrayList<>();
        for (MemberCartItem memberCartItem : memberCartItems) {
            // 填充其他需要返回的数据
            Map<String, Object> map = MyTranslateTools.transEntityToMap(memberCartItem);
            // 商户名字
            MerchantInfo merchantInfo = merchantInfoDAO.selectOne(new QueryWrapper<MerchantInfo>().eq("id", memberCartItem.getMerchantId()));
            map.put("merchantName", merchantInfo.getMerchantName());

            // 规格号
            GoodsSku goodsSku = goodsSkuDAO.selectOne(new QueryWrapper<GoodsSku>().eq("id", memberCartItem.getSkuId()));
            map.put("attrSymbolPath", goodsSku.getAttrSymbolPath());
            items.add(map);
        }

        // 4. 返回提交的购物车项信息
        ResultData resultData = new ResultData();
        resultData.put("item", items);
        return resultData;
    }

    /**
     * 提交订单，生成订单信息业务逻辑处理
     * orderInfo  前端传入部分订单信息（收货地址id、商户id、配送方式id）
     * merchantOrders    以商户为单位报错商品的数组
     * goods             商品数组
     * goodSkuId         商品库id
     * number            商品数量
     * isCartOrder       商品是否来源于购物车，如果是就删除购物车信息
     * orderSource       订单来源（wx、app）
     * @return
     */
    @Override
    public ResultData submitOrderInfo(OrderSubmitDTO orderSubmitDTO, String username) {
        Date gmtCreate = new Date();
        // 用户信息
        SysUser sysUser = sysUserDAO.selectOne(new QueryWrapper<SysUser>().eq("username", username));

        // 全局订单号，购物车的订单有此信息（前缀pubno）
        String orderPubNo = getOrderPubNo(sysUser, gmtCreate);

        // 收货id
        Integer addressId = orderSubmitDTO.getAddressId();
        // 订单来源
        String orderSource = orderSubmitDTO.getOrderSource();

        List<Map<String, Object>> merchantOrdersList = orderSubmitDTO.getMerchantOrders();
        for (Map<String, Object> merchantOrders : merchantOrdersList) {
            // 商户id --> 商户信息
            Integer merchantId = (Integer) merchantOrders.get("merchantId");
            MerchantInfo merchantInfo = merchantInfoDAO.selectOne(new QueryWrapper<MerchantInfo>().eq("id", merchantId));

            // 配送方式id
            Integer deliveryId = (Integer) merchantOrders.get("deliveryId");
            LocationDeliver locationDeliver = locationDeliverDAO.selectOne(new QueryWrapper<LocationDeliver>().eq("delivery_id", deliveryId));

            // 商品信息，商品库id 和 商品数量
            List<Map<String, Object>> goodsList = (List<Map<String, Object>>) merchantOrders.get("goods");
            for (Map<String, Object> map : goodsList) {
                Integer goodSkuId = (Integer) map.get("goodSkuId");
                Integer number = (Integer) map.get("number");

                // 商品库信息（得到价格，计算总价格）
                GoodsSku goodsSku = goodsSkuDAO.selectOne(new QueryWrapper<GoodsSku>().eq("id", goodSkuId));
                BigDecimal price = goodsSku.getPrice().multiply(new BigDecimal(number));

                // 生成订单号
                String orderNo = gerOrderNo(merchantId, gmtCreate);

                // 订单详情表信息添加
                orderInfoDAO.insert(setOrderInfo(orderNo, sysUser, merchantInfo, price, number, locationDeliver, addressId, orderSource, orderPubNo));

                // 商品库表信息添加
                orderSkuDAO.insert(setOrderSku(orderNo, goodsSku, number, price));

                // 订单日志表信息添加
                orderNoteDAO.insert(setOrderNote(orderNo, sysUser, gmtCreate));

                // 如果是购物车中的，删除购物车项信息
                if(orderSubmitDTO.getIsCartOrder().equals("1")){
                    // 查询购物车中信息
                    memberCartItemDAO.delete(new QueryWrapper<MemberCartItem>().eq("sku_id", goodSkuId).eq("merchant_id", merchantId));
                }
            }
        }

        return ResultData.ok(ResultData.OPERATION_SUCCESS, orderPubNo);
    }

    /**
     * 商品库信息封装
     */
    private OrderSku setOrderSku(String orderNo, GoodsSku goodsSku, Integer number, BigDecimal price){
        OrderSku orderSku = new OrderSku();
        orderSku.setGoodId(goodsSku.getGoodId());
        orderSku.setGoodSkuId(goodsSku.getId());
        orderSku.setOrderNo(orderNo);
        orderSku.setNumber(number);
        orderSku.setOrderSubNo("orSub" + orderNo.substring(2));
        orderSku.setOrderSubAmount(price);
        orderSku.setOrderSubStatus(0);
        return orderSku;
    }

    /**
     * 订单详情信息封装
     */
    private OrderInfo setOrderInfo(String orderNo, SysUser sysUser, MerchantInfo merchantInfo,BigDecimal price, Integer number, LocationDeliver locationDeliver, Integer addressId, String orderSource, String orderPubNo){
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderNo(orderNo);
        String orderSn = "tr" + orderNo.substring(2);
        orderInfo.setOrderSn(orderSn);
        orderInfo.setCustomerId(sysUser.getUserId().intValue());
        orderInfo.setMerchantId(merchantInfo.getId());
        orderInfo.setMerchantName(merchantInfo.getMerchantName());
        orderInfo.setProductCount(number);
        orderInfo.setProductAmountTotal(price);
        orderInfo.setOrderStatus(0);
        orderInfo.setAfterStatus(0);
        orderInfo.setOrderAmountTotal(new BigDecimal(0));
        orderInfo.setAddressId(addressId);
        orderInfo.setAdoptFinished(0);
        orderInfo.setOrderSettlementStatus(0);  // 未结算
        orderInfo.setDeliverId(locationDeliver.getDeliveryId());
        orderInfo.setDeliverText(locationDeliver.getWay());
        orderInfo.setLogisticsFee(locationDeliver.getMoney());
        orderInfo.setOrderSource(orderSource);
        orderInfo.setOrderPubNo(orderPubNo);
        return orderInfo;
    }

    /**
     * 订单日志信息封装
     */
    private OrderNote setOrderNote(String orderNo, SysUser sysUser, Date gmtCreate){
        OrderNote orderNote = new OrderNote();
        orderNote.setOrderInfoNo(orderNo);
        orderNote.setOperateContend("创建订单");
        orderNote.setGmtCreate(gmtCreate);
        orderNote.setGmtModified(gmtCreate);
        orderNote.setOperatePersonId(sysUser.getUserId().intValue());
        orderNote.setOperatePerson(sysUser.getMobile());
        return orderNote;
    }

    /**
     * 生成全局订单号
     */
    private String getOrderPubNo(SysUser sysUser, Date gmtCreate){
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        StringBuilder orderNo = new StringBuilder("pubno");
        orderNo.append(format.format(gmtCreate));
        Integer count = orderInfoDAO.selectCount(new QueryWrapper<OrderInfo>().eq("customer_id", sysUser.getUserId()).groupBy("customer_id"));
        for(int i = 0; i < 9-count.toString().length(); i++){
            orderNo.append("0");
        }
        orderNo.append(count.toString());
        return orderNo.toString();
    }

    /**
     * 生成订单号
     */
    private String gerOrderNo(Integer merchantId, Date gmtCreate){
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        StringBuilder orderNo = new StringBuilder("or");
        orderNo.append(format.format(gmtCreate));
        Integer count = orderInfoDAO.selectCount(new QueryWrapper<OrderInfo>().eq("merchant_id", merchantId).groupBy("merchant_id"));
        for(int i = 0; i < 9-count.toString().length(); i++){
            orderNo.append("0");
        }
        orderNo.append(count.toString());
        return orderNo.toString();
    }


    /**
     * 封装购物车商品信息
     */
    private MemberCartItem getMemberCartItem(MemberCart memberCart, GoodsInfo goodsInfo, GoodsSku goodsSku, Integer number, Date gmtCreated){
        MemberCartItem memberCartItem = new MemberCartItem();

        Integer id = memberCart.getId();
        memberCartItem.setCartId(id);
        memberCartItem.setGmtUpdated(gmtCreated);
        memberCartItem.setGmtCreated(gmtCreated);
        // 前端的商品信息
        memberCartItem.setGoodId(goodsInfo.getId());
        memberCartItem.setProductName(goodsInfo.getGoodName());
        memberCartItem.setMerchantId(goodsInfo.getMerchantId().intValue());
        memberCartItem.setNumber(number);

        memberCartItem.setProductImg(goodsSku.getSkuPic());
        memberCartItem.setPrice(goodsSku.getPrice().multiply(new BigDecimal(number)));
        memberCartItem.setSkuId(goodsSku.getId());
        memberCartItem.setProductDesc(goodsSku.getAttrSymbolText());

        // 商品状态  -2失效，-1下架，0无货，1正常
        int status = 1;
        if(goodsSku.getIsHis().equals("1")){
            status = -1;
        }else if(goodsSku.getStock() <= 0){
            status = 0;
        }
        memberCartItem.setStatus(String.valueOf(status));

        return memberCartItem;
    }


    /**
     * 将商品规格码拆分开，得到一个int数组
     */
    private Integer[] getArrayAttrSymbolPath(String attrSymbolPath){
        if(attrSymbolPath == null){
            return null;
        }
        String[] split = attrSymbolPath.split(",");
        Integer[] result = new Integer[split.length];
        for(int i = 0; i < result.length; i++){
            result[i] = Integer.parseInt(split[i]);
        }
        return result;
    }
}

    /*
        2. 生成订单信息（ 注：为购物车中每一项都需创建一个订单信息）
            2.1 订单记录日志：订单号、operate_contend为创建订单、时间、操作人id、操作人手机号
            2.2 订单详情信息：订单号、order_sn、顾客（用户）id、商户id、商户名、商品数量、商品总价
                            订单状态【0未付款】、用户售后状态【0】、实付款金额【0】、运费金额【0】、收货地址编码【0】
                            、adopt_finished(是否是普通订单)【0是】
            2.3 订单库信息：商品id、商品库id、订单号、数量、子订单号、子订单金额、子订单状态【0未付款】
     */
       /* // 2.1 订单记录日志
            // 创建时间
            Date gmtCreate = new Date();
            // 用户信息
            SysUser sysUser = sysUserDAO.selectOne(new QueryWrapper<SysUser>().eq("username", username));
            // 订单号
            String orderNo = getOrderNo(sysUser, gmtCreate);

            // 封装好后，插入数据
            int result = orderNoteDAO.insert(setOrderNote(orderNo, sysUser, gmtCreate));

            // 2.2 订单详情
            // 商户信息
            MerchantInfo merchant = merchantInfoDAO.selectOne(new QueryWrapper<MerchantInfo>().eq("id", memberCartItem.getMerchantId()));

            // 封装好后，插入数据
            int result2 = orderInfoDAO.insert(setOrderInfo(orderNo, sysUser, merchantInfo, memberCartItem));

            // 2.3 订单库
            int result3 = orderSkuDAO.insert(setOrderSku(orderNo, memberCartItem));

            // 3. 删除购物车信息
            if(result3 > 0){
                memberCartItemDAO.delete(new QueryWrapper<MemberCartItem>().eq("id", memberCartItem.getId()));
            }*/
